package com.zx.commonsms.util;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.zx.commonsms.bean.SmsParamBean;
import com.zx.commonsms.bean.SmsParamMultiBean;
import com.zx.commonsms.bean.SmsResultBean;
import com.zx.commonsms.bean.Task;
import com.zx.commonsms.bean.TokenParamBean;
import com.zx.commonsms.bean.TokenResultBean;
import com.zx.commonsms.exception.SmsException;

/**
 * @author zxkj-admin
 * 
 */
public class CommonSmsUtil {

	// 短信平台token，有效时间30分钟，需要使用用户名、密码等从平台获取
	public static String TOKEN="";
	// 从平台获取token的url
	public static final String TOKEN_URL = "http://111.11.84.251/api/get-token/";
	// 从平台发送短信的url
	public static final String SEND_SMS_URL = "http://111.11.84.251/api/send-sms/";
	// 短信平台用户名
	public static final String USER_CODE = "13932121000";
	// 短信平台密码
	public static final String PASSWORD = "nIiSb*dYLPNpa%uxehD5";
	
	
	/**
	 * 发送短信
	 * 
	 * @param task
	 * @return
	 */
	public SmsResultBean sendSms(Task task) {
		
		// 组装参数对象
		SmsParamBean param = new SmsParamBean();
		param.setToken(TOKEN);
		param.setTask(task);

		Gson gson = new Gson();
		String result = null;
		try {// 向平台发送短信任务
			result = httpOperation(SEND_SMS_URL, 
					gson.toJson(param, SmsParamBean.class));
			// 转换发送结果，转换失败会抛出JsonSyntaxException
			SmsResultBean re = gson.fromJson(result, SmsResultBean.class);
			// 如果Token失效
			if (!re.isSuccess()
					&& re.getError_code().equalsIgnoreCase(
							"Token validate failed")) {
				// 重新获取Token
				if (getToken()) {
					param.setToken(TOKEN);
					// 再次发送短信
					result = httpOperation(SEND_SMS_URL, 
							gson.toJson(param, SmsParamBean.class));
					// 转换发送结果
					re = gson.fromJson(result, SmsResultBean.class);
				} else {// 获取Token失败，抛出异常
					throw new SmsException("无发获取Token，无发发送短信");
				}
			}
			return re;
		} catch (SmsException e) {
			e.printStackTrace();
			return null;// 此处可以灵活处理，直接抛出SmsException异常也可以，捕获异常返回空值也可以
		} catch (JsonSyntaxException e) {// 捕获JSON转换异常
			e.printStackTrace();
			return null;// 此处可以灵活处理，直接抛出JsonSyntaxException异常也可以，捕获异常返回空值也可以
		}

	}

	/**
	 * 发送多条不同内容短信
	 * 
	 * @param taskList
	 * @return
	 */
	public SmsResultBean sendSmsMulti(List<Task> taskList) {
		// 组装参数对象
		SmsParamMultiBean param = new SmsParamMultiBean();
		param.setToken(TOKEN);
		param.setTask_list(taskList);

		Gson gson = new Gson();
		String result = null;
		try {// 向平台发送短信任务
			result = httpOperation(SEND_SMS_URL,
					gson.toJson(param, SmsParamMultiBean.class));
			// 转换发送结果，转换失败会抛出JsonSyntaxException
			SmsResultBean re = gson.fromJson(result, SmsResultBean.class);
			// 如果Token失效
			if (!re.isSuccess()
					&& re.getError_code().equalsIgnoreCase(
							"Token validate failed")) {
				// 重新获取Token
				if (getToken()) {
					param.setToken(TOKEN);
					// 再次发送短信
					result = httpOperation(SEND_SMS_URL, 
							gson.toJson(param, SmsParamBean.class));
					// 转换发送结果
					re = gson.fromJson(result, SmsResultBean.class);
				} else {// 获取Token失败，抛出异常
					throw new SmsException("无发获取Token，无发发送短信");
				}
			}
			return re;
		} catch (SmsException e) {
			e.printStackTrace();
			return null;// 此处可以灵活处理，直接抛出SmsException异常也可以，捕获异常返回空值也可以
		} catch (JsonSyntaxException e) {// 捕获JSON转换异常
			e.printStackTrace();
			return null;// 此处可以灵活处理，直接抛出JsonSyntaxException异常也可以，捕获异常返回空值也可以
		}
	}

	/**
	 * 从平台获取Token的方法
	 * 
	 * @return boolean获取Token是否成功
	 */
	public boolean getToken() {
		// 获取nonce32位随机字符
		String nonce = NonceUtil.generateNonce();
		// 获取时间戳
		long timestampNum = System.currentTimeMillis() / 1000;
		String timestamp = String.valueOf(timestampNum);
		// 获取签名
		String signature = processSignature(nonce, timestamp);
		// 组装提交参数
		TokenParamBean param = new TokenParamBean();
		param.setNonce(nonce);
		param.setTimestamp(timestamp);
		param.setSignature(signature);

		Gson gson = new Gson();
		String result = null;
		try {// 获取Token
			result = httpOperation(TOKEN_URL + USER_CODE + "/", 
					gson.toJson(param, TokenParamBean.class));
			if (null != result) {
				TokenResultBean re = gson.fromJson(result,
						TokenResultBean.class);
				if (re.isSuccess()) {// 更新Token
					TOKEN = re.getToken();
					return true;// 返回成功
				} else {
					// 如果返回错误信息是查询太频繁，也返回true
					if (re.getError_code().equalsIgnoreCase(
							"The query is too frequent")) {
						return false;
					} else {
						return false;
					}
				}
			} else {
				return false;
			}
		} catch (SmsException e) {
			e.printStackTrace();
			return false;
		} catch (JsonSyntaxException e) {
			e.printStackTrace();
			return false;
		}

	}

	/**
	 * 处理Signature的方法
	 * 
	 * @param nonce
	 *            32位随机字符串
	 * @param timestamp
	 *            UNIX时间戳
	 * @return 处理好的Signature
	 */
	private String processSignature(String nonce, String timestamp) {
		String password = processPassword();
		String[] triad = { password, nonce, timestamp };
		Arrays.sort(triad, String.CASE_INSENSITIVE_ORDER);// 严格按照字典顺序排序，不区分大小写
		StringBuilder sb = new StringBuilder();
		for (String str : triad) {
			sb.append(str);
		}
		String signature = DigestUtils.shaHex(sb.toString());// 将重新排序的字符数组拼接并用SHA1哈希
		return signature;
	}

	/**
	 * 处理密码的方法
	 * 
	 * @return 处理好的密码
	 */
	private String processPassword() {
		// 如果密码为空，直接用32个空格补齐
		if (StringUtils.isEmpty(PASSWORD)) {
			StringBuilder sb = new StringBuilder();
			for (int i = 0; i < 32; i++) {
				sb.append(" ");
			}
			return sb.toString();
		} else {// 密码不为空，需要判断长度是否超过32
			if (PASSWORD.length() >= 32) {// 长度超过32，截取到32位
				return PASSWORD.substring(0, 32);
			} else {// 长度没超过32，用空格补齐到32位
				int num = 32 - PASSWORD.length();
				StringBuilder sb = new StringBuilder();
				sb.append(PASSWORD);
				for (int i = 0; i < num; i++) {
					sb.append(" ");
				}
				return sb.toString();
			}
		}
	}

	/**
	 * http操作
	 * 
	 * @param url
	 *            要发送请求的url地址
	 * @param paramName
	 *            参数名
	 * @param param
	 *            参数(都是一个JSON格式的数据)
	 * @return
	 */
	private String httpOperation(String url, String param) {
		HttpPost httpRequst = new HttpPost(url);// 创建HttpPost对象

		String result = null;
		try {// 发送http请求
			// 添加要通过post提交的参数
			httpRequst.addHeader("Content-type","application/json; charset=utf-8");  
			httpRequst.setHeader("Accept", "application/json");  
			httpRequst.setEntity(new StringEntity(param, HTTP.UTF_8));  
			HttpResponse httpResponse = new DefaultHttpClient()
					.execute(httpRequst);
			// 判断响应状态码，200为正常响应
			if (httpResponse.getStatusLine().getStatusCode() == 200) {
				HttpEntity httpEntity = httpResponse.getEntity();
				result = EntityUtils.toString(httpEntity);// 取出响应字符串
			} else {// 其他状态为异常，抛出一个运行时异常
				throw new SmsException("网络无发正常连接:状态码"
						+ httpResponse.getStatusLine().getStatusCode());
			}
		} catch (UnsupportedEncodingException e) {// 捕获不支持的编码格式异常
			e.printStackTrace();
			throw new SmsException(e);
		} catch (ClientProtocolException e) {// 捕获协议异常
			e.printStackTrace();
			throw new SmsException(e);
		} catch (IOException e) {// 捕获IO异常
			e.printStackTrace();
			throw new SmsException(e);
		}
		return result;
	}

//	private String readProperties(String propName){
//		Configuration config;
//		String value = "";
//		try {
//			config = new PropertiesConfiguration("sms_token.properties");
//			value = config.getString(propName);
//		} catch (ConfigurationException e) {
//			e.printStackTrace();
//		}
//		return value;
//	}
//	
//	private void writeProperties(String propName,String value){
//		PropertiesConfiguration config;
//		try {
//			config = new PropertiesConfiguration("sms_token.properties");
//			config.setProperty(propName, value);
//			config.save();
//		} catch (ConfigurationException e) {
//			e.printStackTrace();
//		}
//	}
	
	public static void main(String[] args){
		Task task = new Task();
		task.setName("28测试3");
		task.setPhones("13513111027");
		task.setContent("发送测试修改");
		CommonSmsUtil util = new CommonSmsUtil();
		SmsResultBean re = util.sendSms(task);
		System.out.println("");
	}
}
